第20章 Tailwind CSS 实用指南

实用优先的 CSS 框架,快速构建现代 UI

作者:zyyc-0336  |  日期:2026-06-12

本文是前端学习路径第20章(阶段五:外围生态)
上一章:19. 部署与上线 | 下一章:21. 使用第三方React组件
阶段简介:外围生态
前四阶段我们掌握了 HTML/CSS/JS 基础、React 框架、Next.js 全栈开发。从本章开始进入第五阶段:外围生态——学习 Tailwind CSS 原子化样式、第三方组件集成、数据库对接、主题切换等实战技能,让你的项目从"能跑"进化到"好用又好看"。
一句话总结:Tailwind 让你不用写 CSS 文件,直接在 HTML 的 class 里用工具类拼出所有样式。

学习路径建议
原子化 CSS 概念(为什么用 Tailwind)
  ↓
在 Next.js 中安装配置
  ↓
常用工具类(文字/背景/间距/圆角/阴影)
  ↓
响应式前缀(sm:/md:/lg:)
  ↓
暗色模式(dark:)
  ↓
自定义主题
  ↓
实战:用 Tailwind 重写导航栏和文章卡片

20.1 什么是原子化 CSS

概念解释

传统 CSS:给每个组件写一套专属样式。

CSS
/* 传统写法 */
.card {
  padding: 16px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

原子化 CSS:把样式拆成最小粒度的"工具类",直接组合使用。

JSX
<!-- Tailwind 写法:不用写 CSS 文件 -->
<div class="p-4 bg-white rounded-lg shadow-md">
  内容
</div>

两种方式对比

对比项传统 CSSTailwind 原子化
样式写在哪单独的 .css 文件直接写在 class 里
命名自己起类名(.card, .btn)用官方工具类(p-4, bg-white)
复用方式复用类名复用组合(或抽组件)
文件体积可能越来越大自动删除未使用的类,很小
上手难度需要记工具类名
⚠️ "class 那么长,不会很乱吗?" 刚开始确实觉得长,但用熟了比写 CSS 快很多。而且组件化后,样式跟结构在一起,修改时不用 CSS 和 HTML 来回跳。

20.2 在 Next.js 中安装 Tailwind

安装步骤

Bash
# 第 1 步:安装依赖
npm install -D tailwindcss @tailwindcss/postcss postcss

# 第 2 步:初始化配置
npx tailwindcss init

配置 postcss.config.mjs

JS
// postcss.config.mjs
const config = {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};
export default config;

配置全局 CSS

CSS
/* app/globals.css */
@import "tailwindcss";

在 layout.tsx 中引入

TSX
// app/layout.tsx
import "./globals.css";

export default function RootLayout({ children }) {
  return (
    <html lang="zh">
      <body>{children}</body>
    </html>
  );
}

验证安装

TSX
// app/page.tsx
export default function Home() {
  return (
    <h1 className="text-3xl font-bold text-blue-600 p-8">
      Tailwind 安装成功!
    </h1>
  );
}

看到蓝色大标题就说明成功了。

⚠️ 忘记引入 globals.css:Tailwind 不会生效,页面没有样式。
⚠️ 用 className 而不是 class:在 JSX 中必须写 className

20.3 常用工具类速查

20.3.1 文字相关

作用类名等价 CSS
字号text-smfont-size: 0.875rem
字号text-basefont-size: 1rem
字号text-lgfont-size: 1.125rem
字号text-xlfont-size: 1.25rem
字号text-2xlfont-size: 1.5rem
字号text-3xlfont-size: 1.875rem
字重font-normalfont-weight: 400
字重font-boldfont-weight: 700
颜色text-red-500color: #ef4444
颜色text-gray-600color: #4b5563
对齐text-centertext-align: center

20.3.2 背景相关

作用类名等价 CSS
背景色bg-whitebackground: #fff
背景色bg-blue-500background: #3b82f6
背景色bg-gray-100background: #f3f4f6
渐变bg-gradient-to-r向右渐变

20.3.3 间距(padding / margin)

Tailwind 的间距用数字表示,1 = 0.25rem = 4px

类名等价 CSS实际像素
p-1padding: 0.25rem4px
p-2padding: 0.5rem8px
p-4padding: 1rem16px
p-8padding: 2rem32px
m-4margin: 1rem16px
mx-automargin: 0 auto水平居中
mt-4margin-top: 1rem16px
gap-4gap: 1rem16px(flex/grid)

方向前缀t(top)、b(bottom)、l(left)、r(right)、x(左右)、y(上下)

20.3.4 圆角与阴影

作用类名等价 CSS
小圆角roundedborder-radius: 0.25rem
中圆角rounded-lgborder-radius: 0.5rem
大圆角rounded-xlborder-radius: 0.75rem
全圆角rounded-fullborder-radius: 9999px
阴影shadow-sm小阴影
阴影shadow-md中阴影
阴影shadow-lg大阴影

完整示例:一个简单卡片

JSX
export default function Card() {
  return (
    <div className="p-6 bg-white rounded-xl shadow-md">
      <h2 className="text-xl font-bold text-gray-800">
        卡片标题
      </h2>
      <p className="mt-2 text-gray-600">
        这是卡片内容,用了 Tailwind 工具类来设置样式。
      </p>
    </div>
  );
}

逐行讲解

类名作用
容器p-6 bg-white rounded-xl shadow-md内边距24px、白色背景、大圆角、中阴影
标题text-xl font-bold text-gray-800大字号、加粗、深灰色
正文mt-2 text-gray-600上间距8px、浅灰色
⚠️ 间距单位记混p-4 是 16px,不是 4px。记住 数字 × 4 = 像素值
⚠️ 颜色格式:Tailwind 用 颜色名-色阶 格式,如 blue-500,色阶从 50(最浅)到 950(最深)。

20.4 响应式设计(sm:/md:/lg:)

概念解释

Tailwind 的响应式设计用前缀来控制不同屏幕宽度下的样式,默认断点:

前缀最小宽度常见设备
(无前缀)0px手机(默认样式)
sm:640px大手机/小平板
md:768px平板
lg:1024px笔记本
xl:1280px桌面显示器

语法

className="默认样式 sm:小屏样式 md:中屏样式 lg:大屏样式"

先写默认(手机优先),再逐级覆盖。

完整示例:响应式网格

JSX
export default function ResponsiveGrid() {
  return (
    <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 p-4">
      <div className="bg-blue-200 p-4 rounded-lg">卡片 1</div>
      <div className="bg-blue-300 p-4 rounded-lg">卡片 2</div>
      <div className="bg-blue-400 p-4 rounded-lg">卡片 3</div>
      <div className="bg-blue-500 p-4 rounded-lg text-white">卡片 4</div>
    </div>
  );
}

逐行讲解

类名作用
grid启用网格布局
grid-cols-1默认手机:1 列
sm:grid-cols-2640px+:2 列
md:grid-cols-3768px+:3 列
lg:grid-cols-41024px+:4 列
gap-4卡片间距 16px
p-4整体内边距 16px
⚠️ 顺序写反:Tailwind 断点是 min-width,所以默认样式放前面,大屏覆盖放后面。如果写 lg:text-sm text-xl,在大屏上会是 text-xl(因为后面的无前缀类覆盖了前面的)。

正确写法:text-xl lg:text-3xl(手机大字,电脑更大)

20.5 暗色模式(dark:)

概念解释

Tailwind 内置暗色模式支持,用 dark: 前缀定义暗色主题下的样式。

配置方式

tailwind.config.js 中设置策略:

JS
// tailwind.config.js(Tailwind v4 可通过 CSS 变量配置)
// 这里演示 v3 的配置方式
/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: "class", // 用 class 切换暗色模式
  content: ["./app/**/*.{js,ts,jsx,tsx}"],
  theme: { extend: {} },
  plugins: [],
};
darkMode: "class" 表示在 <html> 标签上加 dark 类来激活暗色模式。

语法

className="亮色样式 dark:暗色样式"

完整示例:支持暗色模式的卡片

JSX
export default function DarkCard() {
  return (
    <div className="p-6 bg-white dark:bg-gray-800 rounded-xl shadow-md">
      <h2 className="text-xl font-bold text-gray-800 dark:text-white">
        标题
      </h2>
      <p className="mt-2 text-gray-600 dark:text-gray-300">
        内容
      </p>
    </div>
  );
}

逐行讲解

类名亮色效果暗色效果
bg-white dark:bg-gray-800白色背景深灰背景
text-gray-800 dark:text-white深灰文字白色文字
text-gray-600 dark:text-gray-300灰色文字浅灰文字

切换暗色模式的 JS 代码

JSX
// 一个简单的切换按钮组件
"use client";
import { useState, useEffect } from "react";

export default function ThemeToggle() {
  const [dark, setDark] = useState(false);

  useEffect(() => {
    document.documentElement.classList.toggle("dark", dark);
  }, [dark]);

  return (
    <button
      onClick={() => setDark(!dark)}
      className="px-4 py-2 rounded-lg bg-gray-200 dark:bg-gray-700
                 text-gray-800 dark:text-white"
    >
      {dark ? "☀️ 亮色模式" : "🌙 暗色模式"}
    </button>
  );
}
⚠️ 忘记配置 darkMode:不配置的话 dark: 前缀不生效。
⚠️ 暗色样式和亮色样式冲突:不要同时写 bg-white bg-gray-800,必须用 dark: 前缀区分。

20.6 自定义主题

概念解释

当默认颜色、间距不够用时,可以在配置中扩展主题。

方式一:tailwind.config.js 扩展(v3)

JS
// tailwind.config.js
module.exports = {
  content: ["./app/**/*.{js,ts,jsx,tsx}"],
  theme: {
    extend: {
      colors: {
        brand: "#6366f1",       // 自定义品牌色
        "brand-light": "#818cf8",
      },
      spacing: {
        "128": "32rem",         // 自定义间距
      },
      fontFamily: {
        custom: ["Noto Sans SC", "sans-serif"],
      },
    },
  },
};

使用方式:

JSX
<div className="bg-brand text-brand-light font-custom p-128">
  自定义主题
</div>

方式二:CSS 变量(v4 推荐)

CSS
/* globals.css */
@import "tailwindcss";

@theme {
  --color-brand: #6366f1;
  --color-brand-light: #818cf8;
  --font-family-custom: "Noto Sans SC", sans-serif;
}

使用方式和上面一样:bg-brandfont-custom

常用自定义项

要自定义的配置 key使用类名
颜色colors.brandbg-brand, text-brand
字体fontFamily.customfont-custom
间距spacing.128p-128, m-128
圆角borderRadius.2xlrounded-2xl
⚠️ v3 和 v4 配置方式不同:v3 用 tailwind.config.js,v4 推荐用 CSS @theme
⚠️ 修改配置后需要重启开发服务器:否则新主题不生效。

20.7 实战:重写导航栏和文章卡片

20.7.1 用 Tailwind 写导航栏

TSX
// components/Navbar.tsx
"use client";
import Link from "next/link";

export default function Navbar() {
  return (
    <nav className="bg-white dark:bg-gray-900 shadow-md sticky top-0 z-50">
      <div className="max-w-6xl mx-auto px-4 py-3 flex items-center justify-between">
        {/* Logo */}
        <Link href="/" className="text-xl font-bold text-blue-600 dark:text-blue-400">
          MyBlog
        </Link>

        {/* 导航链接 */}
        <div className="flex gap-6">
          <Link href="/" className="text-gray-700 dark:text-gray-300 hover:text-blue-500 transition">
            首页
          </Link>
          <Link href="/about" className="text-gray-700 dark:text-gray-300 hover:text-blue-500 transition">
            关于
          </Link>
          <Link href="/blog" className="text-gray-700 dark:text-gray-300 hover:text-blue-500 transition">
            博客
          </Link>
        </div>
      </div>
    </nav>
  );
}

逐行讲解

类名作用
bg-white dark:bg-gray-900亮色白底,暗色深灰底
shadow-md底部阴影
sticky top-0固定在页面顶部
z-50层级最高,不被遮挡
max-w-6xl mx-auto最大宽度 1152px,水平居中
px-4 py-3左右 padding 16px,上下 12px
flex items-center justify-between弹性布局,垂直居中,两端对齐
gap-6链接间距 24px
hover:text-blue-500悬停变蓝
transition颜色过渡动画

20.7.2 用 Tailwind 写文章卡片

TSX
// components/ArticleCard.tsx
interface ArticleCardProps {
  title: string;
  summary: string;
  date: string;
  tag: string;
}

export default function ArticleCard({ title, summary, date, tag }: ArticleCardProps) {
  return (
    <article className="bg-white dark:bg-gray-800 rounded-xl shadow-md
                        hover:shadow-lg transition-shadow duration-300 overflow-hidden">
      {/* 标签和日期 */}
      <div className="px-6 pt-5 flex items-center justify-between">
        <span className="text-xs font-medium px-3 py-1 rounded-full
                         bg-blue-100 dark:bg-blue-900 text-blue-700 dark:text-blue-300">
          {tag}
        </span>
        <time className="text-sm text-gray-400">{date}</time>
      </div>

      {/* 标题和摘要 */}
      <div className="px-6 py-4">
        <h3 className="text-lg font-bold text-gray-800 dark:text-white
                       hover:text-blue-600 dark:hover:text-blue-400 cursor-pointer">
          {title}
        </h3>
        <p className="mt-2 text-sm text-gray-500 dark:text-gray-400 line-clamp-2">
          {summary}
        </p>
      </div>

      {/* 底部按钮 */}
      <div className="px-6 pb-5">
        <button className="text-sm text-blue-600 dark:text-blue-400
                           hover:underline font-medium">
          阅读全文 →
        </button>
      </div>
    </article>
  );
}

使用示例

TSX
// app/page.tsx
import Navbar from "@/components/Navbar";
import ArticleCard from "@/components/ArticleCard";

export default function Home() {
  return (
    <div className="min-h-screen bg-gray-50 dark:bg-gray-900">
      <Navbar />

      <main className="max-w-6xl mx-auto px-4 py-8">
        <h1 className="text-3xl font-bold text-gray-800 dark:text-white mb-8">
          最新文章
        </h1>

        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
          <ArticleCard
            title="Next.js 入门教程"
            summary="从零开始学习 Next.js,了解 App Router、数据获取和部署。"
            date="2026-06-12"
            tag="Next.js"
          />
          <ArticleCard
            title="Tailwind CSS 实用指南"
            summary="掌握原子化 CSS 的核心概念和常用工具类。"
            date="2026-06-12"
            tag="CSS"
          />
          <ArticleCard
            title="React Hooks 深入理解"
            summary="useState、useEffect、useRef 等核心 Hooks 的原理和用法。"
            date="2026-06-10"
            tag="React"
          />
        </div>
      </main>
    </div>
  );
}
⚠️ line-clamp-2 不生效:需要确认 Tailwind 版本支持,或手动添加 CSS。
⚠️ overflow-hidden 别忘了:卡片圆角 + 阴影时,不加这个可能导致内容溢出圆角。

20.8 本章复盘

核心知识点总结

知识点关键内容一句话记忆
原子化 CSS用最小粒度的类名组合样式不写 CSS 文件,样式写在 class 里
安装配置npm install tailwindcss + @import "tailwindcss"装包 → 配置 → 引入全局 CSS
文字类text-xl, font-bold, text-gray-600text-大小 font-粗细 text-颜色
背景类bg-white, bg-blue-500bg-颜色名-色阶
间距类p-4, m-2, gap-4数字×4=像素
圆角阴影rounded-lg, shadow-mdrounded-大小, shadow-大小
响应式sm:, md:, lg:手机优先,前缀覆盖大屏
暗色模式dark:bg-gray-800dark: 前缀 + class 模式
自定义主题@themetailwind.config.jsextend 里加自定义颜色/字体

新手速记口诀

间距数字乘以四,颜色名字带色阶
响应前缀 sm/md/lg,暗色 dark 冒号写前面
手机优先写默认,大屏覆盖写后面

常见错误速查

错误现象原因解决方案
样式完全不生效忘记引入 globals.css检查 @import "tailwindcss"
JSX 中 class 报错应该用 classNameclassclassName
响应式不生效断点顺序写反默认样式在前,大屏覆盖在后
暗色模式不生效没配置 darkMode配置 darkMode: "class"
自定义颜色无效修改配置后没重启重启 npm run dev
间距值不对记错换算关系p-4 = 16px,不是 4px

本章复盘——Tailwind CSS 核心要点

要点说明
原子化 CSS每个类名只做一件事,组合使用
响应式sm/md/lg 前缀,手机优先设计
暗色模式dark: 前缀,class 或 media 策略
自定义主题tailwind.config.js 扩展颜色/字体

下一章预告(第21章):我们将学习使用第三方 React 组件——站在巨人的肩膀上,用 npm 安装现成的轮子(Markdown 渲染器、音视频播放器等),快速给博客添加强大功能。

本文档由 zyyc-0336 编写,最后更新:2026-06-14